{% from pinInitializerImport import makePinInitializer as makePinInitializer %}
/**
 * \file
 * \brief Definitions of low-level SD/MMC card drivers for SDMMCv1 in {{ board }} ({{ dictionary['chip']['compatible'][0] }} chip)
 *
 * \author Copyright (C) 2019-2020 Kamil Szczygiel https://distortec.com https://freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at https://mozilla.org/MPL/2.0/.
 *
 * \warning
 * Automatically generated file - do not edit!
 */

#include "distortos/chip/sdmmcs.hpp"

#include "distortos/chip/dmas.hpp"
#include "distortos/chip/PinInitializer.hpp"
#include "distortos/chip/SdMmcCardLowLevel.hpp"
#include "distortos/chip/STM32-SDMMCv1-SdmmcPeripheral.hpp"

#include "distortos/BIND_LOW_LEVEL_INITIALIZER.h"

/**
 * \brief Generates name of DMA channel object in the form `dma<dmaId>Channel<channelId>`.
 *
 * \param [in] dmaId is a DMA identifier
 * \param [in] channelId is a DMA channel identifier
 */

#define DMA_CHANNEL(dmaId, channelId)	CONCATENATE4(dma, dmaId, Channel, channelId)

namespace distortos
{

namespace chip
{
{% for key, sdmmc in dictionary['SDMMCs'].items() if sdmmc is mapping and 'ST,STM32-SDMMC-v1' in sdmmc['compatible'] %}

#ifdef DISTORTOS_CHIP_{{ key | upper }}_ENABLE

/*---------------------------------------------------------------------------------------------------------------------+
| {{ key | upper }}
+---------------------------------------------------------------------------------------------------------------------*/

namespace
{

{% set ckPresent = 'CK' in sdmmc %}
{% set cmdPresent = 'CMD' in sdmmc %}
{% set d0Present = 'D0' in sdmmc %}
{% set d1Present = 'D1' in sdmmc %}
{% set d2Present = 'D2' in sdmmc %}
{% set d3Present = 'D3' in sdmmc %}
{% set pinSum0 = ckPresent + cmdPresent + d0Present %}
{% set pinSum1 = pinSum0 + d1Present + d2Present + d3Present %}
{% if (pinSum0 != 0 and pinSum0 != 3) or (pinSum1 != 0 and pinSum1 != 3 and pinSum1 != 6) %}
{% raise 'Allowed combinations of pins for {}: none, {{CK, CMD, D0}} or {{CK, CMD, D[0-3]}}'.format(key) %}
{% endif %}
{% for pinKey in ['CK', 'CMD', 'D0', 'D1', 'D2', 'D3'] if pinKey in sdmmc %}
{% if loop.first == True %}
/// pin initializers for {{ key | upper }}
const PinInitializer {{ key | lower }}PinInitializers[]
{
{% endif %}
		// {{ key | upper }} {{ pinKey }}
		{{ makePinInitializer(sdmmc[pinKey]) | indent(8) | replace('    ', '\t') }}
{% if loop.last == True %}
};

{% endif %}
{% endfor %}
/**
 * \brief Low-level chip initializer for {{ key | upper }}
 *
 * This function is called before constructors for global and static objects via BIND_LOW_LEVEL_INITIALIZER().
 */

void {{ key | lower }}LowLevelInitializer()
{
#if defined(RCC_APB2ENR_{{ key | upper }}EN)
	RCC->APB2ENR |= RCC_APB2ENR_{{ key | upper }}EN;
#else
	#error "Unsupported bus for {{ key | upper }}!"
#endif
{% if pinSum1 != 0 %}

	for (auto& pinInitializer : {{ key | lower }}PinInitializers)
		pinInitializer();
{% endif %}
}

BIND_LOW_LEVEL_INITIALIZER(50, {{ key | lower }}LowLevelInitializer);

/// raw {{ key | upper }} peripheral
const SdmmcPeripheral {{ key | lower }}Peripheral {{ '{' }}{{ key | upper }}_BASE, {{ key | lower }}clkFrequency};

}	// namespace

SdMmcCardLowLevel {{ key | lower }}
{
		{{ key | lower }}Peripheral,
		DMA_CHANNEL(DISTORTOS_CHIP_{{ key | upper }}_DMA, DISTORTOS_CHIP_{{ key | upper }}_DMA_CHANNEL),
		DISTORTOS_CHIP_{{ key | upper }}_DMA_REQUEST
};

/**
 * \brief {{ sdmmc['interrupt']['vector'] }} interrupt handler
 */

extern "C" void {{ sdmmc['interrupt']['vector'] }}_IRQHandler()
{
	{{ key | lower }}.interruptHandler();
}

#endif	// def DISTORTOS_CHIP_{{ key | upper }}_ENABLE
{% endfor %}

}	// namespace chip

}	// namespace distortos
